import createVanilla from 'zustand/vanilla'
import { subscribeWithSelector } from 'zustand/middleware'
import create from 'zustand'
import { store as addMtStore } from '../../store'
import { store as addMtSelectedStore } from '../selected/store'
import { fetchPendingInit, fetchTemplatesSearch, fetchUser, fetchUserLike } from '@/api/addMt'
import {
	DepartmentUser,
	flatList,
	getItemInPending,
	pendingDepartmentTranslator,
	PendingItem,
	pendingModelTranslator,
	pendingMonitorTranslator,
	PendingMtModel,
	pendingSearchTreeTranslator,
	pendingTemplateListTranslator,
	pendingTemplateTranslator,
	pendingTotalNumTranslator,
	TreeNode,
} from '../../translator'
import { ExpandTreeParams } from '@/api/addMt/interface'
import { CONSTANT } from '../../utils/utils'
import { useGlobalStore } from '@/store/global'

type PendingOption = {
	tree: PendingMtModel<TreeNode>[]
	list: PendingItem[]
	_prevClickSelectItem: { start: string; prevChosen: string[] } | null
	isSearch: boolean
	searchType: null | 1 | 2
	totalNum: number
}
type IStore = PendingOption & {
	update: (d: Partial<PendingOption>) => void
	reset: () => void
	fetchInit: () => void
	fetchSimpleSearch: (fromSearchVal: string) => void
	fetchAllSearch: (fromSearchVal: string) => void
	fetchTemplate: () => void
	fetchDepartmentUser: (params: Omit<ExpandTreeParams, 'public_group_moid' | 'is_all'>, id: string) => void
	fetchGroupUser: (params: Pick<ExpandTreeParams, 'public_group_moid'>, id: string) => void
	clearAllSelected: () => void
	collapsedAll: () => void
	toggleTree: (data: PendingItem<TreeNode>, searchType: 1 | 2 | null) => void
	clickSelectItem: (data: PendingItem, { ctrlKey, shiftKey }: { ctrlKey: boolean; shiftKey: boolean }) => void
	openMoreOptions: (data: PendingItem) => void
	removeAllSelected: () => void
	removeItemSelected: (data: PendingItem) => void
}
const initialState: PendingOption = {
	tree: [],
	list: [],
	_prevClickSelectItem: null,
	isSearch: false,
	searchType: null,
	totalNum: 0,
}

export const store = createVanilla<IStore>()(
	subscribeWithSelector((set, get) => ({
		...initialState,
		update: (d) => set({ ...d }),
		reset: () => set(initialState),
		fetchInit: async () => {
			const showTrees = addMtStore.getState().showTrees
			const SWITCH = useGlobalStore.getState().SWITCH
			set({ isSearch: false, searchType: null, totalNum: 0 })
			const res = await fetchPendingInit()
			//空值搜索，只有组织架构，无任何人员信息
			if (res) {
				const { lists: departments } = res
				const departmentModel = pendingDepartmentTranslator(departments)
				const monitor = [pendingMonitorTranslator()]
				const template = [pendingTemplateTranslator()]
				set({
					tree: [
						...(showTrees.includes('org') ? departmentModel : []),
						...(showTrees.includes('monitor') && SWITCH.addMt.monitor ? monitor : []),
						...(showTrees.includes('template') ? template : []),
					],
				})
			}
		},
		fetchSimpleSearch: async (fromSearchVal: string) => {
			const showTrees = addMtStore.getState().showTrees
			const [res, resT] = await Promise.all([
				fetchUserLike(fromSearchVal, 7),
				showTrees.includes('template') ? fetchTemplatesSearch(fromSearchVal) : Promise.resolve(undefined),
			])
			if (!res && !resT) {
				set({ isSearch: true, searchType: CONSTANT.searchType.simple, totalNum: 0 })
				return null
			}
			const depts = res ? res : { lists: [], user_size_data: {} }
			const templates =
				resT && resT.list ? { list: resT.list.slice(0, 7), total: resT.total } : { list: [], total: 0 }
			const _data = {
				departments: depts.lists,
				templates: templates.list,
				user_size_data: { ...depts.user_size_data, template: templates.total },
			}
			const tree = pendingSearchTreeTranslator(_data, fromSearchVal, showTrees)
			const totalNum = pendingTotalNumTranslator(_data, showTrees)
			set({ tree, isSearch: true, searchType: CONSTANT.searchType.simple, totalNum })
		},
		fetchAllSearch: async (fromSearchVal: string) => {
			const showTrees = addMtStore.getState().showTrees
			const [res, resT] = await Promise.all([
				fetchUserLike(fromSearchVal, 150),
				showTrees.includes('template') ? fetchTemplatesSearch(fromSearchVal) : Promise.resolve(undefined),
			])
			if (!res && !resT) {
				set({ isSearch: true, searchType: CONSTANT.searchType.all, totalNum: 0 })
				return null
			}
			const depts = res ? res : { lists: [], user_size_data: {} }
			const templates = resT && resT.list ? { list: resT.list, total: resT.total } : { list: [], total: 0 }
			const _data = {
				departments: depts.lists,
				templates: templates.list,
				user_size_data: { ...depts.user_size_data, template: templates.total },
			}
			const tree = pendingSearchTreeTranslator(_data, fromSearchVal, showTrees)
			const totalNum = pendingTotalNumTranslator(_data, showTrees)
			set({ tree, isSearch: true, searchType: CONSTANT.searchType.all, totalNum })
		},
		fetchTemplate: async () => {
			const res = await fetchTemplatesSearch('')
			if (res && res.list) {
				const templateModel = pendingTemplateListTranslator(res.list)
				set((state) => {
					let templateNode = state.tree.find((x) => x.id === CONSTANT.pendingRootId.template)
					if (templateNode) {
						templateNode.users = templateModel
					}
					return { tree: [...state.tree] }
				})
			}
		},
		fetchDepartmentUser: async (params, id) => {
			const res = await fetchUser(params)
			if (res) {
				const { users } = res
				const tree = get().tree
				getItemInPending(tree, (item) => {
					if (item.id === id) {
						item.users = users.map((x) => {
							let userNode = pendingModelTranslator(new DepartmentUser(x))
							userNode.id = item.id + '$$' + userNode.item.moid
							userNode.pid = item.id
							userNode.attr.fromSearchVal = ''
							userNode.nestingLevel = item.nestingLevel + 1
							return userNode
						})
					}
				})
				set({ tree: [...tree] })
			}
		},
		fetchGroupUser: async (params, id) => {
			const res = await fetchUser(params)
			if (res) {
				const { users } = res
				const tree = get().tree
				getItemInPending(tree, (item) => {
					if (item.id === id) {
						item.users = users.map((x) => {
							let userNode = pendingModelTranslator(new DepartmentUser(x))
							userNode.id = item.id + '$$' + userNode.item.moid
							userNode.pid = item.id
							userNode.attr.fromSearchVal = ''
							userNode.nestingLevel = item.nestingLevel + 1
							return userNode
						})
					}
				})
				set({ tree: [...tree] })
			}
		},
		clearAllSelected: () => {
			const tree = get().tree
			getItemInPending(tree, (item) => {
				item.status.isSelected = false
				item.status.isOpenMoreOpt = false
				item.users.forEach((x) => {
					x.status.isSelected = false
					x.status.isOpenMoreOpt = false
				})
			})
			set({ tree: [...tree] })
		},
		collapsedAll: () => {
			const tree = get().tree
			getItemInPending(tree, (item) => {
				item.status.isOpen = false
			})
			set({ tree: [...tree] })
		},
		toggleTree: (data: PendingItem<TreeNode>, searchType: 1 | 2 | null) => {
			const tree = get().tree
			const { item, status, id, pid } = data
			if (!status.isOpen) {
				//不是搜索需要请求下级
				if (searchType === null) {
					if (item.type === 'template') {
						get().fetchTemplate()
					} else if (item.type === 'group') {
						//非根节点
						if (pid !== '') {
							let _temp = id.split('_')
							if (_temp[1]) {
								get().fetchGroupUser({ public_group_moid: _temp[1] }, id)
							}
						}
					} else if (item.type === 'org') {
						//非根节点
						if (pid !== '') {
							let _temp = id.split('_')
							if (_temp[1]) {
								get().fetchDepartmentUser({ department_moid: _temp[1], user_domain_moid: _temp[0] }, id)
							}
						}
					}
				}
			}
			status.isOpen = !status.isOpen
			set({ tree: [...tree] })
		},
		clickSelectItem: (data, { ctrlKey, shiftKey }) => {
			let prevClickSelectItem = get()._prevClickSelectItem
			const tree = get().tree
			const list = get().list
			if (shiftKey) {
				if (prevClickSelectItem) {
					const { start, prevChosen } = prevClickSelectItem
					if (prevChosen.length > 0) {
						//说明已经有过一次shift操作，需要把这次操作结果复原
						for (const item of list) {
							if (prevChosen.includes(item.id)) {
								item.status.isSelected = false
							}
						}
					}
					const startItem = list.find((x) => x.id === start)
					let newChosen = []
					if (!startItem || startItem.id === data.id) {
						//比如经过搜索，初始值没了，那就重新记录;或者初始值和当前值一样
						data.status.isSelected = true
						prevClickSelectItem.start = data.id
					} else {
						let _flag = false,
							_time = 0
						for (const item of list) {
							if (item.id === data.id || item.id === start) {
								item.status.isSelected = true
								newChosen.push(item.id)
								_flag = ++_time === 1
							}
							if (_flag) {
								item.status.isSelected = true
								newChosen.push(item.id)
							}
						}
					}
					prevClickSelectItem.prevChosen = newChosen
				} else {
					data.status.isSelected = true
					prevClickSelectItem = { start: data.id, prevChosen: [] }
				}
			} else {
				if (ctrlKey) {
					data.status.isSelected = !data.status.isSelected
				} else {
					getItemInPending(tree, (item) => {
						item.status.isSelected = false
						item.status.isOpenMoreOpt = false
						item.users.forEach((x) => {
							x.status.isSelected = false
							x.status.isOpenMoreOpt = false
						})
					})
					data.status.isSelected = true
				}
				prevClickSelectItem = { start: data.id, prevChosen: [] }
			}
			set({ tree: [...tree], _prevClickSelectItem: prevClickSelectItem })
		},
		openMoreOptions: (data: PendingItem) => {
			const tree = get().tree
			data.status.isOpenMoreOpt = true
			set({ tree: [...tree] })
		},
		removeAllSelected: () => {
			const tree = get().tree
			getItemInPending(tree, (item) => {
				item.status.isSelected = false
				item.users.forEach((x) => {
					x.status.isSelected = false
				})
			})
			set({ tree: [...tree] })
		},
		removeItemSelected: (data) => {
			const tree = get().tree
			data.status.isSelected = false
			set({ tree: [...tree] })
		},
	}))
)
function dependenceToList({
	tree = store.getState().tree,
	mccCurrentMts = addMtStore.getState().mccCurrentMts,
	selectedMts = addMtSelectedStore.getState().selectedList,
}) {
	const list = flatList(
		tree,
		mccCurrentMts,
		selectedMts.map((x) => x.item)
	)
	store.setState({ list })
}
addMtStore.subscribe(
	(state) => state.mccCurrentMts,
	(mccCurrentMts) => {
		dependenceToList({ mccCurrentMts })
	}
)
store.subscribe(
	(state) => state.tree,
	(tree) => {
		dependenceToList({ tree })
	}
)
addMtSelectedStore.subscribe(
	(state) => state.selectedList.length,
	() => {
		const selectedMts = addMtSelectedStore.getState().selectedList
		dependenceToList({ selectedMts })
	}
)
export const usePendingStore = create(store)
